<?php

namespace App\Http\Controllers\Api;


use App\Http\Forms\UserForm;
use App\Library\OSS;
use App\Library\RateLimiter;
use App\Modules\Common\Models\PageConfig;
use App\Modules\Coupon\Manager;
use App\Modules\Coupon\Models\Coupon;
use App\Modules\Coupon\Models\GiveCoupon;
use App\Modules\Coupon\Models\UserCoupon;
use App\Modules\Free\Models\FreeRecord;
use App\Modules\Order\Models\Order;
use App\Modules\Rebate\Models\Rebate;
use App\Modules\Shop\Shop;
use App\Modules\User\Models\Account;
use App\Modules\User\Models\AccountDetail;
use App\Modules\User\Models\ApplyPartner;
use App\Modules\User\Models\BindUser;
use App\Modules\User\Models\Feedback;
use App\Modules\User\Models\Member;
use App\Modules\User\Models\OldUser;
use App\Modules\User\Models\User;
use App\Modules\User\Models\UserAddress;
use App\Modules\User\Models\UserVisitor;
use App\Modules\User\ShareRank;
use App\Modules\User\UnlockRank;
use App\Modules\User\VisitorRank;
use App\Modules\Withdrawal\Models\BankInfo;
use App\Modules\Withdrawal\Models\Withdrawal;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Overtrue\LaravelWeChat\Facade as EasyWeChat;
use Illuminate\Routing\UrlGenerator;
use EasyWeChat\OfficialAccount\Application;
use Ramsey\Uuid\Uuid;
use function foo\func;
use App\Modules\Recharge\RechargeRecord;
use App\Modules\Recharge\UserBalance;


class UserController extends ApiController
{
    public function getInfo()
    {
        $user = $this->getUser();
        $shop = collect();
        if (!empty($user->shop_id)) {
            $shop = Shop::query()->whereIn('id', $user->shop_id)->get();
        }
        $user->last_time = now()->toDateTimeString();
        $user->save();

        /**
         * 返利订单统计
         *
         * 待审核    type = init;    status = init
         * 待提现    type = issued;  status = issued
         * 提现中    type = ing;     status = finish && withdrawal_status = pending
         * 累计提现  type = total;   withdrawal_status = success
         */
        $account = $user->getAccount();
        $order['init']   = Rebate::query()->where('user_id', '=', $user->id)->where('status', '=', 'init')->sum('money');
        // $order['issued'] = Rebate::query()->where('user_id', '=', $user->id)->where('status', '=', 'issued')->sum('money');
        $order['ing']    = Rebate::query()->where('user_id', '=', $user->id)->where('status', '=', 'finish')->where('withdrawal_status', '=', 'pending')->sum('money');
        $order['total']  = Rebate::query()->where('user_id', '=', $user->id)->where('withdrawal_status', '=', 'success')->sum('money');
        $order['issued'] = $account['money'];//待提现
        // $order['total']  = $account['income'];//累计提现

        $order['init']   = empty($order['init'])   ? 0 : (int)$order['init']   / 100;
        $order['issued'] = empty($order['issued']) ? 0 : (int)$order['issued'] / 100;
        $order['ing']    = empty($order['ing'])    ? 0 : (int)$order['ing']    / 100;
        $order['total']  = empty($order['total'])  ? 0 : (int)$order['total']  / 100;

        //查询充值余额
        $balance = UserBalance::query()->where('user_id', $user->id)->selectRaw('sum(balance) as balance')->first()->toArray();

        //个人中心订单数量
        $orderNum = [
            'init'     => Order::query()->where('user_id', $user->id)->where('status', 'init')->count(),//待支付
            'paid'     => Order::query()->where('user_id', $user->id)->where('status', 'paid')->where('is_prepay', 1)->where('is_finish', 0)->count(),//已支付(支付定金、未支付尾款)
            'received' => Order::query()->where('user_id', $user->id)->where('status', 'paid')->where('is_finish', 0)->where('final_payment', 1)->count(),//待收货（完成全部支付）
            'return'   => Order::query()->where('user_id', $user->id)->where('status', 'refund')->count(),//退换/售后
            'evaluate' => Order::query()->where('user_id', $user->id)->where('status', 'paid')->where('is_comment', 0)->where('is_finish', 1)->count(),//待评价
        ];

        return $this->success([
            'id' => $user->id,
            'nickname' => $user->nickname,
            'avatar' => $user->avatar,
            'level' => $user->level,
            'referrer_id' => $user->referrer_id,
            'invite_code' => $user->invite_code,
            'shop' => $user->level == 3 ? $shop->map(function ($item) {
                return [
                    'id' => $item->id,
                    'name' => $item->name,
                ];
            }) : null,
            'has_order' => $user->has_order,
            'mobile' => $user->mobile,
            'employee_identity' => $user->level == 3 ? $user->employee_identity : null,
            'position' => $user->level == 3 ? $user->position : null,
            'name' => $user->name,
            'order' => $order,//返利订单统计数据
            'order_num' => $orderNum,//个人中心订单数量
            'balance' => $balance['balance'],//余额
            'is_palm_management' => $user->is_palm_management,//是否开通权限
        ]);
    }

    /**
     * 充值记录
     */
    public function getRechargeRecord(Request $request)
    {

        $user = $this->getUser();
        $this->validate($request, [
            'offset' => 'integer',
            'count' => 'integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $rechargeRecords = RechargeRecord::query()
            ->where('recharge_records.user_id', '=', $user->id)
            ->leftJoin('shops AS s', 'recharge_records.shop_id', '=', 's.id')
            ->orderBy('recharge_records.created_at', 'desc');

        $data = $rechargeRecords
            ->offset($offset)
            ->limit($count)
            ->get(['recharge_records.*', 's.id as shop_id', 's.name as shop_name', 's.cover'])
            ->map(function ($item) {
                if ($item->cover) {
                    $item->cover = OSS::instance()->getUrl($item->cover);
                }
                return $item;
            });

        return $this->success($data);
    }

    public function getMemberShop()
    {
        $user = $this->getUser();
        return $this->success();
    }

    public function getBaseInfo(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $re = User::query()
            ->where('id', $id)
            ->select('nickname', 'avatar', 'level', 'name')
            ->first();
        return $this->success($re);
    }

    public function syncUserInfo(Request $request)
    {
        $this->validateWith([
            'encrypted_data' => 'required|string',
            'iv' => 'required|string',
        ]);

        $encryptedData = $request->input('encrypted_data');
        $iv = $request->input('iv');
        $user = $this->getUser();
        $app = EasyWeChat::miniProgram();
        try {
            $userInfo = $app->encryptor->decryptData($user->session_key, $iv, $encryptedData);
            $tmpName = tempnam(sys_get_temp_dir(), "avatar-");
            copy($userInfo['avatarUrl'], $tmpName);
            //TODO test
//            OSS::instance()->storeFile('avatar/'.$user->id.".png", $tmpName);
        } catch (\Throwable $e) {
            return $this->fail("session_key过期", 1001);
        }
        if (empty($user->nickname)) {
            $userData = [
                'unionid' => $userInfo['unionId'] ?? null,
                'nickname' => !empty($userInfo['nickName']) ? $userInfo['nickName'] : '',
                'avatar' => !empty($userInfo['avatarUrl']) ? $userInfo['avatarUrl'] : '',
                'gender' => !empty($userInfo['gender']) ? $userInfo['gender'] : '',
                'avatar_key' => 'avatar/' . $user->id . ".png",
            ];
            $user->update($userData);
            /**
             *  临洮：会员注册成功
             *  模板ID：gfTm6gK2_DLagdMPi6Pficckl0EoxSRxVX10AIIqsgk
             *  格式：
             *          {{first.DATA}}
             * 昵称：{{keyword1.DATA}}
             * 账户：{{keyword2.DATA}}
             * 注册时间：{{keyword3.DATA}}
             * {{remark.DATA}}
             */
            $sendData = [$user->openid, $user->nickname, $user->id, date("Y年m月d日 H时i分s秒")];
            sendMessage(3, $sendData);
        }

        if (empty($user->unionid)) {
            Auth::guard()->logout();
        }
        return $this->success();
    }

    public function bindReferrer(Request $request)
    {
        $this->validate($request, [
            'id' => "required|integer",
        ]);
        $id = $request->input('id');
        $user = $this->getUser();
        $user->referrer_id = $id;
        $user->save();
        return $this->success();
    }

    public function visitor(Request $request)
    {
        $this->validate($request, [
            'referrer_id' => 'required|integer',
        ]);
        $referrerId = $request->input('referrer_id');
        $user = $this->getUser();
        UserVisitor::query()
            ->create([
                'user_id' => $user->id,
                'referrer_id' => $referrerId,
            ]);
        return $this->success();
    }

    public function getUnlock()
    {
        $user = $this->getUser();
        $re = Member::query()
            ->where('user_id', $user->id)
            ->selectRaw("sum(quota) as `lock`, sum(rebate) as `unlock`")
            ->first();
        return $this->success([
            'unlock' => $re->unlock ?? 0,
            'lock' => $re->lock - $re->unlock ?? 0,
        ]);
    }

    public function getAccount(Request $request)
    {
        $this->validate($request, [
            'id' => 'nullable|integer',
        ]);
        $id = $request->input('id');
        $user = $this->getUser();

        if (!is_null($id)) {
            $user = User::query()
                ->where('id', $id)
                ->where('referrer_id', $user->id)
                ->first();
            if (is_null($user)) {
                return $this->fail('不能查看该用户账户信息');
            }
        }

        $account = $user->getAccount();
        return $this->success($account->money);
    }

    public function getAccountDetail(Request $request)
    {
        $this->validate($request, [
            'offset' => 'required|integer',
            'count' => 'required|integer',
        ]);
        $user = $this->getUser();
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $re = AccountDetail::query()
            ->where('user_id', $user->id)
            ->orderBy('created_at')
            ->offset($offset)
            ->limit($count)
            ->get();
        return $this->success($re);
    }

    public function getAddressList(Request $request)
    {
        $this->validate($request, [
            'offset' => 'integer',
            'count' => 'integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $user = $this->getUser();
        $address = UserAddress::query()
            ->where('user_id', $user->id)
            ->offset($offset)
            ->limit($count)
            ->get();
        return $this->success($address);
    }

    public function addAddress(Request $request)
    {
        $this->validate($request, [
            'title' => 'nullable|string',
            'name' => 'required|string',
            'mobile' => 'required|string',
            'province' => 'nullable|string',
            'city' => 'nullable|string',
            'district' => 'nullable|string',
            'detail' => 'nullable|string',
            'is_default' => 'nullable|boolean',
        ]);
        $user = $this->getUser();
        $title = $request->input('title');
        $name = $request->input('name');
        $mobile = $request->input('mobile');
        $province = $request->input('province');
        $city = $request->input('city');
        $district = $request->input('district');
        $detail = $request->input('detail');
        $isDefault = $request->input('is_default');
        if ($isDefault) {
            UserAddress::query()
                ->where('user_id', $user->id)
                ->where('is_default', 1)
                ->update([
                    'is_default' => 0,
                ]);
        }
        UserAddress::query()
            ->create([
                'user_id' => $user->id,
                'title' => $title,
                'name' => $name,
                'mobile' => $mobile,
                'province' => $province,
                'city' => $city,
                'district' => $district,
                'detail' => $detail,
                'is_default' => $isDefault,
            ]);
        return $this->success();
    }

    public function updateAddress(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
            'title' => 'nullable|string',
            'name' => 'required|string',
            'mobile' => 'required|string',
            'province' => 'nullable|string',
            'city' => 'nullable|string',
            'district' => 'nullable|string',
            'detail' => 'nullable|string',
            'is_default' => 'nullable|boolean',
        ]);
        $user = $this->getUser();
        $id = $request->input('id');
        $title = $request->input('title');
        $name = $request->input('name');
        $mobile = $request->input('mobile');
        $province = $request->input('province');
        $city = $request->input('city');
        $district = $request->input('district');
        $detail = $request->input('detail');
        $isDefault = $request->input('is_default');
        if ($isDefault) {
            UserAddress::query()
                ->where('user_id', $user->id)
                ->where('is_default', 1)
                ->update([
                    'is_default' => 0,
                ]);
        }
        UserAddress::query()
            ->where('id', $id)
            ->where('user_id', $user->id)
            ->update([
                'user_id' => $user->id,
                'title' => $title,
                'name' => $name,
                'mobile' => $mobile,
                'province' => $province,
                'city' => $city,
                'district' => $district,
                'detail' => $detail,
                'is_default' => $isDefault,
            ]);
        return $this->success();
    }

    public function delAddress(Request $request)
    {
        $this->validate($request, [
            'id' => "required|integer",
        ]);
        $id = $request->input('id');
        $user = $this->getUser();
        UserAddress::query()
            ->where('user_id', $user->id)
            ->where('id', $id)
            ->delete();
        return $this->success();
    }

    public function setDefaultAddress(Request $request)
    {
        $this->validate($request, [
            'id' => "required|integer",
        ]);
        $user = $this->getUser();
        $id = $request->input('id');
        UserAddress::query()
            ->where('user_id', $user->id)
            ->where('is_default', 1)
            ->update([
                'is_default' => 0,
            ]);
        UserAddress::query()
            ->where('user_id', $id)
            ->where('id', 1)
            ->update([
                'is_default' => 1,
            ]);
        return $this->success();
    }

    public function getDefaultAddress()
    {
        $user = $this->getUser();
        $re = UserAddress::query()
            ->where('user_id', $user->id)
            ->orderBy('is_default')
            ->first();
        return $this->success($re);
    }

    public function getUserCouponList(Request $request)
    {
        $this->validate($request, [
            'offset' => 'integer',
            'count' => 'integer',
            'status' => 'required|string',
        ]);
        $offset = $request->input('offset');
        $count = $request->input('count');
        $status = $request->input('status');
        $user = $this->getUser();
        $query = UserCoupon::query()
            ->where('user_id', $user->id);
        if ($status == 'useable') {
            $query->where('expiration_date', ">=", Carbon::now()->toDateString())
                ->whereNull('use_id');
        } elseif ($status == 'overdue') {
            $query->where('expiration_date', '<', Carbon::now()->toDateString())
                ->whereNotNull('use_id');
        } else {
            $query->whereNotNull('use_id');
        }

        $coupon = $query->offset($offset)
            ->limit($count)
            ->get();
        $shops = Shop::query()->whereIn('id', $coupon->pluck('shop_id')->all())->get()->keyBy('id');
        $coupon = $coupon->map(function ($item) use ($shops) {
            $item->shop_name = empty($item->shop_id) ? "" : $shops->get($item->shop_id)->name;
            return $item;
        });
        return $this->success($coupon);
    }

    public function getCouponList(Request $request)
    {
        $this->validate($request, [
            'offset' => 'nullable|integer',
            'count' => 'nullable|integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $user = $this->getUser();
        $query = Coupon::query()
            ->orderBy('created_at', 'desc');
        if ($user->level == 1) {
            $member = Member::query()->where('user_id', $user->id)->get();
            $query->whereIn('shop_id', $member->pluck('shop_id')->all());
        }
        $coupon = $query->offset($offset)
            ->limit($count)
            ->get();
        $shops = Shop::query()->whereIn('id', $coupon->pluck('shop_id')->all())->get()->keyBy('id');
        $re = $coupon->map(function ($item) use ($shops) {
            $item->share_image = empty($item->share_image) ? '' : OSS::instance()->getUrl($item->share_image);
            $item->shop = $shops->get($item->shop_id);
            return $item;
        });
        return $this->success($re);
    }

    public function getGoodsCoupon(Request $request)
    {
        $this->validate($request, [
            'shop_id' => 'required|integer',
            'id' => 'required|integer',
        ]);
        $shopId = $request->input('shop_id');
        $id = $request->input('id');
        $coupon = Coupon::query()
            ->where('shop_id', $shopId)
            ->where(function ($q) use ($id) {
                return $q->whereNull('applicable')
                    ->orWhereJsonContains('applicable', [(string)$id]);
            })
            ->get();
        $shops = Shop::query()->whereIn('id', $coupon->pluck('shop_id')->all())->get()->keyBy('id');
        $re = $coupon->map(function ($item) use ($shops) {
            $item->share_image = empty($item->share_image) ? '' : OSS::instance()->getUrl($item->share_image);
            $item->shop = $shops->get($item->shop_id);
            return $item;
        });
        return $this->success($re);
    }

    public function getGiftCoupon()
    {
//        $coupon = Coupon::query()
//            ->where('is_gift', 1)
//            ->first();
//        if (is_null($coupon)) {
//            return $this->fail('没有可领取的券');
//        }
//        return $this->success($coupon);
    }

    public function giveCoupon(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $this->getUser();
        $user = $this->getUser();
        if ($user->level < 2) {
            return $this->fail('你没有赠送权限');
        }
        $coupon = Coupon::query()->find($id);
        if (is_null($coupon)) {
            return $this->fail('优惠券不可用');
        }
        $code = Uuid::uuid4()->getHex();
        GiveCoupon::query()
            ->create([
                'coupon_id' => $coupon->id,
                'code' => $code
            ]);
        return $this->success($code);
    }

    public function takeCoupon(Request $request)
    {
        $this->validate($request, [
            'code' => 'required|string',
        ]);
        $code = $request->input('code');
        $user = $this->getUser();

        $give = GiveCoupon::query()
            ->whereNull('receiver')
            ->where('code', $code)
            ->first();
        if (is_null($give)) {
            return $this->fail('无效领取码');
        }
        /** @var Coupon $coupon */
        $coupon = Coupon::query()
            ->find($give->coupon_id);
//        $userCoupon = UserCoupon::query()
//            ->where('user_id', $user->id)
//            ->where('is_gift', 1)
//            ->first();
//        if (!is_null($userCoupon)) {
//            return $this->fail('没有可领取的优惠券');
//        }
        Manager::sendCoupon($coupon, $user);
        $give->receiver = $user->id;
        $give->save();
        return $this->success();
    }

    public function bindUser(Request $request)
    {
        $this->validate($request, [
            'mobile' => 'required|integer',
            'name' => 'required|string',
        ]);
        $name = $request->input('name');
        $mobile = $request->input('mobile');
        $user = $this->getUser();
        $t = User::query()
            ->where('mobile', $mobile)
            ->where('id', '!=', $user->id)
            ->first();
        if (!is_null($t)) {
            return $this->fail('手机号已经注册');
        }
        BindUser::query()->create([
            'mobile' => $mobile,
            'user_id' => $user->id,
            'name' => $name,
        ]);
        return $this->success();
    }

    public function initMobile(Request $request)
    {
        $this->validate($request, [
            'mobile' => 'required|string',
        ]);
        $mobile = $request->input('mobile');
        $user = $this->getUser();
        $tmp = User::query()
            ->where('mobile', $mobile)
            ->first();
        if (!is_null($tmp)) {
            return $this->fail('电话号已经注册');
        }
        if (empty($user->mobile)) {
            $user->mobile = $mobile;
//            $old = OldUser::query()
//                ->where('mobile', $mobile)
//                ->first();
//            if (!is_null($old) && $user->level < 1) {
//                $user->level = 1;
//
//            }
            $user->save();
        }
        Auth::guard()->logout();
        return $this->success();
    }

    public function applyPartner(Request $request)
    {
        $this->validate($request, [
            'code' => "required|string",
            'name' => "required|string",
            'id_number' => "required|string",
            'address' => "required|string",
            'company' => "required|string",
            'job' => "required|string",
            'image' => "required|string",
            'id_card_positive' => "required|string",
            'id_card_back' => "required|string",
        ]);
        $code = $request->input('code');
        $name = $request->input('name');
        $id_number = $request->input('id_number');
        $address = $request->input('address');
        $company = $request->input('company');
        $job = $request->input('job');
        $image = $request->input('image');
        $id_card_positive = $request->input('id_card_positive');
        $id_card_back = $request->input('id_card_back');
        $page = PageConfig::query()->first();
        if (!$page->can_apply_partner) {
            return $this->fail('申请没有开放');
        }
        $user = $this->getUser();
        if ($user->level == 2) {
            return $this->fail("已经是合伙人");
        }
        $invite = User::query()
            ->where('level', 3)
            ->where('invite_code', $code)
            ->first();
        if (is_null($invite)) {
            return $this->fail('邀请码错误');
        }
        ApplyPartner::query()
            ->firstOrCreate([
                'user_id' => $user->id,
                'status' => ApplyPartner::STATUS_INIT,
            ], [
                'personal_id' => $invite->id,
                'name' => $name,
                'id_number' => $id_number,
                'address' => $address,
                'company' => $company,
                'job' => $job,
                'image' => $image,
                'id_card_positive' => $id_card_positive,
                'id_card_back' => $id_card_back,
            ]);
        $invite->invite_code = \App\Modules\User\Manager::getInviteCode();
        $invite->save();
        return $this->success();
    }

    public function getPartnerApplication()
    {
        $user = $this->getUser();
        $application = ApplyPartner::query()
            ->where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->first();
        if (is_null($application)) {
            return $this->success();
        } elseif ($user->level != 2 && $application->status == ApplyPartner::STATUS_PASS) {
            return $this->success();
        }
        $application->image = OSS::instance()->getUrl($application->image);
        $application->id_card_positive = OSS::instance()->getUrl($application->id_card_positive);
        $application->id_card_back = OSS::instance()->getUrl($application->id_card_back);
        return $this->success($application);
    }

    public function getReferrerList(Request $request)
    {
        $this->validate($request, [
            'shop_id' => 'nullable|array',
            'name' => 'nullable|string',
            'offset' => 'nullable|string',
            'count' => 'nullable|string',
        ]);
        $name = $request->input('name');
        $shopId = $request->input('shop_id');
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $user = $this->getUser();

        $query = User::query()
            ->where(function ($q) use ($shopId) {
                return $q->where('users.level', '>', 1)
                    ->orWhereExists(function ($q2) use ($shopId) {
                        return $q2->select(DB::raw(1))
                            ->from('members')
                            ->whereRaw("members.user_id = users.id and shop_id in(?)", [$shopId]);
                    });
            })
            ->where('users.level', '>', 0);
        if (!empty($name)) {
            $query->where(function ($q) use ($name) {
                return $q->where('users.name', 'like', "%$name%")
                    ->orwhere('users.mobile', 'like', "%$name%");
            });
        }
        $re = $query
            ->offset($offset)
            ->limit($count)
            ->get()
            ->map(function ($item) {
                return [
                    'id' => $item->id,
                    'name' => $item->name,
                    'mobile' => $item->mobile,
                    'nickname' => $item->nickname,
                    'avatar' => $item->avatar,
                ];
            });
        return $this->success($re);
    }

    public function getReferrer()
    {
        $user = $this->getUser();
        $id = $user->referrer_id;
        if (empty($id)) {
            return $this->success();
        }
        $re = User::query()
            ->find($id);
        return $this->success([
            'id' => $re->id,
            'name' => $re->name,
            'mobile' => $re->mobile,
            'nickname' => $re->nickname,
            'avatar' => $re->avatar,
        ]);
    }

    public function checkReferrer(Request $request)
    {
        $this->validate($request, [
            'shop_id' => 'required|array',
            'user_id' => 'nullable|integer',
        ]);
        $shopId = $request->input('shop_id');
        $userId = $request->input('user_id');
        $user = $this->getUser();

        if (!empty($userId)) {
            $referrer = User::query()->find($userId);

            if ($referrer->level > 1) {
                return $this->success([
                    'id' => $referrer->id,
                    'name' => $referrer->name,
                    'mobile' => $referrer->mobile,
                ]);
            } elseif ($referrer->level == 1) {
                $member = Member::query()
                    ->whereIn('shop_id', $shopId)
                    ->where('user_id', $userId)
                    ->get();
                if (!is_null($member)) {
                    return $this->success([
                        'id' => $referrer->id,
                        'name' => $referrer->name,
                        'mobile' => $referrer->mobile,
                    ]);
                }
            }
        }
        if ($user->level > 1) {
            return $this->success([
                'id' => $user->id,
                'name' => $user->name,
                'mobile' => $user->mobile,
            ]);
        } elseif ($user->level == 1) {
            $member = Member::query()
                ->whereIn('shop_id', $shopId)
                ->where('user_id', $this->id)
                ->get();
            if (!empty($member)) {
                return $this->success([
                    'id' => $user->id,
                    'name' => $user->name,
                    'mobile' => $user->mobile,
                ]);
            }
        }
        return $this->success();
    }

    public function invitationStatistics()
    {
        $user = $this->getUser();
        $re = [
            'invite_number' => 0,
            'no_deal' => 0,
            'order_number' => 0,
        ];
        $bind = User::query()
            ->where('referrer_id', $user->id)
            ->selectRaw('count(1) as count, count(if(has_order = 1, 1, null)) as order_number')
            ->first();
        $rebate = Rebate::query()
            ->where('user_id', $user->id)
            ->count();
        $re['invite_number'] = $bind->count;
        $re['no_deal'] = $bind->count;
        $re['order_number'] = $rebate;
        return $this->success($re);
    }

//    public function getBankInfo()
//    {
//        $user = $this->getUser();
//        $bank = BankInfo::query()
//            ->where('user_id', $user->id)
//            ->first();
//        return $this->success($bank);
//    }

    public function setBankInfo(Request $request)
    {
        $this->validate($request, [
            'id' => 'nullable|integer',
            'name' => 'required|string',
            'bank_name' => 'required|string',
            'no' => 'required|string',
        ]);
        $user = $this->getUser();
        $id = $request->input('id');
        $name = $request->input('name');
        $bankName = $request->input('bank_name');
        $no = $request->input('no');
        if (empty($id)) {
            BankInfo::query()
                ->create([
                    'user_id' => $user->id,
                    'name' => $name,
                    'bank_name' => $bankName,
                    'no' => $no,
                ]);
        } else {
            BankInfo::query()
                ->where('id', $id)
                ->where('user_id', $user->id)
                ->update([
                    'name' => $name,
                    'bank_name' => $bankName,
                    'no' => $no,
                ]);
        }

        return $this->success();
    }

    public function destoryBankInfo(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $user = $this->getUser();
        BankInfo::query()
            ->where('id', $id)
            ->where('user_id', $user->id)
            ->delete();
        return $this->success();
    }

    public function getBank(Request $request)
    {
        $this->validate($request, [
            'offset' => 'nullable|integer',
            'count' => 'nullable|integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $user = $this->getUser();
        $re = BankInfo::query()
            ->where('user_id', $user->id)
            ->offset($offset)
            ->limit($count)
            ->get();
        return $this->success($re);
    }

    public function getBankDetail(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $user = $this->getUser();
        $re = BankInfo::query()
            ->where('id', $id)
            ->where('user_id', $user->id)
            ->first();
        return $this->success($re);
    }

    public function applyWithdrawal(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $user = $this->getUser();
        $bank = BankInfo::query()
            ->where('id', $id)
            ->where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->first();
        if (is_null($bank)) {
            return $this->fail('银行卡信息错误');
        }
        DB::beginTransaction();
        $account = $user->getAccount();
        if ($account->money <= 0) {
            return $this->fail('余额不足');
        }

        $money = $account->money;
        $account->decreaseMoney($money, "bank", "提现");
        $orderId = [];
        $rebateId = [];
        \App\Modules\Rebate\Manager::rebateFinish($user, $money, $orderId, $rebateId);

        $model = Order::query()->whereIn("id", array_unique($orderId))->get()->toArray();
        $array_column = array_column($model, "shop_id");
        $array_column = array_unique($array_column);
        $array_column = array_merge($array_column, []);
        Withdrawal::query()
            ->create([
                'user_id' => $user->id,
                'title' => "银行卡 " . $bank->no,
                'money' => $money,
                'status' => Withdrawal::STATUS_INIT,
                'channel' => 'bank',
                'link_id' => $bank->id,
                'rebate_id' => array_unique($rebateId),
                'order_id' => array_unique($orderId),
                'shop_id' => $array_column
            ]);
        DB::commit();
        return $this->success();
    }

    public function getWithdrawalDetail(Request $request)
    {
        $this->validate($request, [
            'offset' => 'nullable|integer',
            'count' => 'nullable|integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $user = $this->getUser();

        $withdrawal = Withdrawal::query()
            ->where('user_id', $user->id)
            ->offset($offset)
            ->limit($count)
            ->orderBy('created_at', 'desc')
            ->get()
            ->map(function ($item) {
                $item->certificate = file_url($item->certificate);
                return $item;
            });
        return $this->success($withdrawal);
    }

    public function getWithdrawalOrder(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer'
        ]);
        $id = $request->input('id');
        $user = $this->getUser();
        $withdrawal = Withdrawal::query()
            ->where('id', $id)
            ->where('user_id', $user->id)
            ->first();
        if (is_null($withdrawal)) {
            return $this->fail('ID错误');
        }
        $order = Order::query()
            ->whereIn('id', $withdrawal->order_id)
            ->get();
        $shops = Shop::query()->whereIn('id', $order->pluck('shop_id')->all())->get()->keyBy('id');

        $rebates = Rebate::query()
            ->where('user_id', $user->id)
            ->where('origin', Order::class)
            ->whereIn('link_id', $order->pluck('id')->all())
            ->get()
            ->keyBy('link_id');
        $re = $order->map(function ($item) use ($shops, $rebates) {
            $shop = $shops->get($item->shop_id);
            $rebate = $rebates->get($item->id);
            $rebateStatus = null;
            if (!is_null($rebate)) {
                if ($rebate->status == Rebate::STATUS_FINISH) {
                    $rebateStatus = Rebate::$withdrawalStatusShow[$rebate->withdrawal_status];
                } else {
                    $rebateStatus = Rebate::$statusShow[$rebate->status];
                }
            }
            return [
                'id' => $item->id,
                'type' => $item->type,
                'title' => $item->title,
                'price' => $item->price,
                'original_price' => $item->original_price,
                'link_id' => $item->link_id,
                'coupon_pay' => $item->coupon_pay,
                'refund_fee' => $item->refund_fee,
                'number' => $item->number,
                'cover' => $item->cover,
                'status' => $item->status,
                'delivery' => $item->delivery,
                'is_comment' => $item->is_appraised,
                'is_finish' => $item->is_finish,
                'is_prepay' => $item->prepay,
                'detail' => $item->detail,
                'buyer_confirm' => $item->buyer_confirm,
                'gift' => $item->gift,
                'shop' => $shop->name,
                'rebate_status' => $rebateStatus,
                'rebate_money' => $rebate->money,
                'mobile' => $item->mobile,
                'name' => $item->name,
                'we_chat_pay_time' => $item->we_chat_pay_time
            ];
        });
        return $this->success($re);
    }

    public function getVisitorRank(Request $request)
    {
        $this->validate($request, [
            'offset' => 'integer',
            'count' => 'integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $re = VisitorRank::getList($offset, $count);
        $ids = array_keys($re);
        $user = User::query()
            ->whereIn('id', $ids)
            ->get()
            ->map(function ($item) use ($re) {
                $rank = VisitorRank::getRank($item->id);
                return [
                    'nickname' => $item->nickname,
                    'avatar' => $item->avatar,
                    'score' => $re[$item->id],
                    'rank' => $rank + 1,
                ];
            });
        return $this->success($user);
    }

    /**
     * 返利排行
     */
    public function getUnlockRank(Request $request)
    {
        // UnlockRank::refresh();
        // dd('完成');
        $this->validate($request, [
            'interval' => 'required|string',
            'offset'   => 'required|integer',
            'count'    => 'required|integer',
        ]);
        $interval  = $request->input('interval');
        $offset    = $request->input('offset');
        $count     = $request->input('count');
        // $shop_name = $request->input('shop_name', '');
        $year      = $request->input('year', '');

        $list = [];
        $year = (int)$year > 0 ? $year : '';

        UnlockRank::setKey($interval.$year);
        $list = UnlockRank::getList($offset, $count);
        $ids = array_keys($list);
        $users = User::query()
            ->whereIn('id', $ids)
            ->get()
            ->keyBy('id');
        $re = [];
        foreach ($list as $key => $value) {
            $user = $users->get($key);
            $re[] = [
                'nickname' => $user->nickname,
                'avatar' => $user->avatar,
                'score' => $value,
            ];
        }
        return $this->success($re);
    }

    /**
     * 返利排行 门店选择
     */
    public function getUnlockRankShop(Request $request)
    {
        $this->validate($request, [
            'interval' => 'required|string',
            'offset'   => 'required|integer',
            'count'    => 'required|integer',
        ]);
        $interval  = $request->input('interval');
        $offset    = $request->input('offset', 0);
        $count     = $request->input('count', 20);
        $shop_name = $request->input('searchName', '');
        $year      = $request->input('year', '');

        $list = [];
        $year = (int)$year > 0 ? $year : '';

        $query = Member::query()
                    ->leftjoin('users', 'users.id', '=', 'members.user_id')
                    ->leftjoin('shops', 'shops.id', '=', 'members.shop_id')
                    ->where('users.level', 1)
                    ->select('members.*')
                    ->selectRaw('sum(members.rebate) as score,members.user_id,users.nickname,users.avatar,shops.name as shop_name')
                    ->groupBy('members.user_id')
                    ->orderBy('score', 'desc');

        if ($interval == 'quarterly') {//季度

            $query->where('members.created_at', '>', now()->startOfQuarter()->toDateTimeString());

        }else if ($interval == 'annual') {//年度

            $query->where('members.created_at', '>', now()->startOfYear()->toDateTimeString());

        }else if ($interval == 'previous'){//往年

            if ($year) {// 带年份
                $query->where('members.created_at', '>=', $year . '-01-01 00:00:00');
                $query->where('members.created_at', '<=', $year . '-12-31 23:59:59');
            }else{// 不带年份
                $query->where('members.created_at', '<', now()->startOfYear()->toDateTimeString());
            }

        }

        if ($shop_name) {
            $query->where('shops.name', 'like', "%".$shop_name."%");
        }   

        $data = $query
                ->offset($offset)
                ->limit($count)
                ->get();
        
        return $this->success($data);
    }

    /**
     * 返利排行
     */
    public function getUnlockRankOld(Request $request)
    {
        $this->validate($request, [
            'offset' => 'integer',
            'count' => 'integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $list = UnlockRank::getList($offset, $count);
        $ids = array_keys($list);
        $users = User::query()
            ->whereIn('id', $ids)
            ->get()
            ->keyBy('id');
        $re = [];
        foreach ($list as $key => $value) {
            $user = $users->get($key);
            $re[] = [
                'nickname' => $user->nickname,
                'avatar' => $user->avatar,
                'score' => $value,
            ];
        }
        return $this->success($re);
    }

    public function getShareRank(Request $request)
    {
        $this->validate($request, [
            'offset' => 'integer',
            'count' => 'integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $re = ShareRank::getList($offset, $count);
        $ids = array_keys($re);
        $user = User::query()
            ->whereIn('id', $ids)
            ->get()
            ->map(function ($item) use ($re) {
                $rank = ShareRank::getRank($item->id);
                return [
                    'nickname' => $item->nickname,
                    'avatar' => $item->avatar,
                    'score' => $re[$item->id],
                    'rank' => $rank + 1,
                ];
            });
        return $this->success($user);
    }

    public function getAccountRank()
    {
        $user = $this->getUser();


        $account = $user->getAccount();
        $before = Account::query()
            ->where('income', ">", $account->income)->count();
        return $this->success([
            'max' => $account->income ?? 0,
            'ratio' => 1,
            'rank' => $before + 1,
        ]);
    }

    public function getJsSdkConfig(UrlGenerator $generator, Application $application)
    {
        $application->jssdk->setUrl($generator->previous());
        $signature = $application->jssdk->getConfigArray([]);
        return $this->success($signature);
    }

    public function getInvited(Request $request)
    {
        $this->validate($request, [
            'offset' => "nullable|integer",
            'count' => "nullable|integer",
            'has_order' => 'required|boolean',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $hasOrder = $request->input('has_order');
        $user = $this->getUser();
        if ($hasOrder) {
            $data = User::query()
                ->where('referrer_id', $user->id)
                ->where('has_order', $hasOrder)
                ->offset($offset)
                ->limit($count)
                ->get();

        } else {
            $data = BindUser::query()
                ->leftJoin('users', 'users.mobile', '=', 'bind_users.mobile')
                ->where('bind_users.user_id', $user->id)
                ->where(function ($q) use ($user) {
                    return $q->whereNull('users.referrer_id')
                        ->orWhere(function ($q2) use ($user) {
                            $q2->where('users.referrer_id', $user->id)
                                ->orWhere('users.has_order', 0);
                        });
                })
                ->select('users.id', 'users.nickname', 'bind_users.name', 'users.avatar', 'bind_users.mobile')
                ->orderBy('bind_users.created_at', 'desc')
                ->offset($offset)
                ->limit($count)
                ->get();
        }

        $coupon = UserCoupon::query()
            ->whereIn('user_id', $data->pluck('id')->all())
            ->where('is_gift', 1)
            ->get()
            ->groupBy('user_id');
        $data = $data->map(function ($item) use ($user, $coupon) {
            return [
                'id' => $item->id,
                'nickname' => $item->nickname ?? ($item->name ?? ""),
                'avatar' => $item->avatar,
                'mobile' => $item->referrer_id == $user->id ? $item->mobile : "",
                'has_coupon' => is_null($coupon->get($item->id)) ? 0 : 1,
            ];
        });
        return $this->success($data);
    }

    public function getPageConfig()
    {
        $page = PageConfig::query()->first();
        return $this->success($page);
    }

    public function getTeam(Request $request)
    {
        $this->validate($request, [
            'id' => 'required|integer',
        ]);
        $id = $request->input('id');
        $user = $this->getUser();
        $member = User::query()
            ->where('id', $id)
            ->where('referrer_id', $user->id)
            ->first();
        if (is_null($member)) {
            return $this->fail("不能查看该用户信息");
        }

        $member = Member::query()
            ->where('user_id', $user->id)
            ->selectRaw('sum(quota) as aim, sum(rebate) as unlock')
            ->first();
        $rebate = Rebate::query()->where('user_id', $member->id)->where('status', Rebate::STATUS_ISSUED)->sum('money');
        $invite = User::query()->where('referrer_id', $id)->count();
        $noDeal = BindUser::query()
            ->leftJoin('users', 'users.mobile', '=', 'bind_users.mobile')
            ->where('bind_users.user_id', $id)
            ->where(function ($q) use ($id) {
                return $q->whereNull('users.referrer_id')
                    ->orWhere(function ($q2) use ($id) {
                        $q2->where('users.referrer_id', $id)
                            ->orWhere('users.has_order', 0);
                    });
            })
            ->count();
        $deal = User::query()->where('referrer_id', $id)->where('has_order', 1)->count();
        $re = [
            'lock' => $member->aim - $member->unlock,
            'unlock' => $member->unlock,
            'rebate' => $rebate,
            'invite' => $invite,
            'no_deal' => $noDeal,
            'deal' => $deal,
        ];
        return $this->success($re);
    }

    public function search(Request $request)
    {
        $this->validate($request, [
            'search' => 'required|string',
            'offset' => 'nullable|integer',
            'count' => 'nullable|intgerr',
        ]);
        $search = $request->input('search');
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);

        $re = User::query()
            ->where(function ($q) use ($search) {
                return $q->where('name', 'like', '%' . $search . '%')
                    ->orWhere('mobile', 'like', '%' . $search . '%');
            })
            ->offset($offset)
            ->limit($count)
            ->get()
            ->map(function ($item) {
                return [
                    'id' => $item->id,
                    'nickname' => $item->nickname,
                    'name' => $item->name,
                    'mobile' => $item->mobile,
                ];
            });
        return $this->success($re);
    }

    public function getMemberInfo(Request $request)
    {
        $this->validate($request, [
            'offset' => 'nullable|integer',
            'count' => 'nullable|integer',
        ]);
        $offset = $request->input('offset', 0);
        $count = $request->input('count', 10);
        $user = $this->getUser();
        $data = Member::query()
            ->where('user_id', $user->id)
            ->offset($offset)
            ->limit($count)
            ->get();
        $rebates = Rebate::query()
            ->where('user_id', $user->id)
            ->whereIn('shop_id', $data->pluck('shop_id')->all())
            ->where('level', 1)
            ->whereIn('status', [Rebate::STATUS_FINISH, Rebate::STATUS_ISSUED])
            ->selectRaw('sum(money) as money, shop_id')
            ->groupBy('shop_id')
            ->get()
            ->keyBy('shop_id');
        $shops = Shop::query()
            ->whereIn('id', $data->pluck('shop_id')->all())
            ->get()
            ->keyBy('id');
        $re = $data->map(function ($item) use ($shops, $rebates) {
            $rebate = $rebates->get($item->shop_id);
            $shop = $shops->get($item->shop_id);
            return [
                'shop_id' => $item->shop_id,
                'cover' => OSS::instance()->getUrl($shop->cover),
                'shop' => $shop->name,
                'quota' => $item->quota,
                'rebate' => $rebate->money ?? 0,
            ];
        });
        return $this->success($re);
    }

    public function getBindMobileCode(Request $request)
    {
        $this->validate($request, [
            'mobile' => 'required|string',
        ]);
        $mobile = $request->input('mobile');
        $user = $this->getUser();
        if (
            !RateLimiter::limitBy("bind:mobile:" . $mobile, 2, 1) &&
            !RateLimiter::limitBy("bind:mobile:" . $mobile, 10, 60)
        ) {
            return $this->fail('超出频率限制');
        }
        $serialNumber = \App\Modules\User\Manager::createMobileVerification($user, 86, $mobile);

        return $this->success($serialNumber);
    }

    public function bindMobile(Request $request)
    {
        $this->validate($request, [
            'serial_number' => 'required|string',
        ]);

        $serialNumber = $request->input('serial_number');
        $code = $request->input('code', '');
        $user = $this->getUser();
        \App\Modules\User\Manager::checkMobileVerification($user, $serialNumber);
        return $this->success();
    }

    /**
     * 绑定手机，原来的
     */
    // public function bindMobile(Request $request)
    // {
    //     $this->validate($request, [
    //         'serial_number' => 'required|string',
    //         'code' => 'required|string|size:6',
    //     ]);

    //     $serialNumber = $request->input('serial_number');
    //     $code = $request->input('code');
    //     $user = $this->getUser();
    //     \App\Modules\User\Manager::checkMobileVerification($user, $serialNumber, $code);
    //     return $this->success();
    // }

    public function feedback(Request $request)
    {
        $this->validate($request, [
            'name' => 'required|string',
            'mobile' => 'required|string ',
            'content' => 'required|string',
            'image' => 'nullable|array',
        ]);
        $name = $request->input('name');
        $mobile = $request->input('mobile');
        $content = $request->input('content');
        $image = $request->input('image');
        $user = $this->getUser();

        Feedback::query()
            ->create([
                'user_id' => $user->id,
                'name' => $name,
                'mobile' => $mobile,
                'content' => $content,
                'title' => $image,
            ]);
        return $this->success();
    }

    public function getExclusiveService(Request $request)
    {
        $user = $this->getUser();
        if (empty($user->personal_id)) {
            return $this->success();
        }
        $invite = User::query()
            ->where('id', $user->personal_id)
            ->first();
        return $this->success([
            'name' => $invite->name,
            'avatar' => $invite->avatar,
            'mobile' => $invite->mobile,
        ]);
    }

    /**
     * 充值金额
     */
    public function getBalanceList(Request $request){
        $this->validate($request, [
            'offset' => 'nullable|integer',
            'count'  => 'nullable|integer',
        ]);
        $offset = $request->input('offset', 0);
        $count  = $request->input('count', 10);
        $user   = $this->getUser();

        $aData = DB::table('user_balances')
                ->leftJoin('shops', 'user_balances.shop_id', '=', 'shops.id')
                ->where('user_balances.user_id', $user->id)
                ->offset($offset)
                ->limit($count)
                ->get(['shops.name','shops.cover','user_balances.*']);

        foreach ($aData as $key => $value) {
            $value->cover = !empty($value->cover) ? OSS::instance()->getUrl($value->cover) : '';
        }
        return $this->success($aData);
    }

    /**
     * 消费记录
     */
    public function getConsumeList(Request $request){
        $this->validate($request, [
            'offset' => 'nullable|integer',
            'count'  => 'nullable|integer',
        ]);
        $offset = $request->input('offset', 0);
        $count  = $request->input('count', 10);
        $user   = $this->getUser();

        $query = Order::query()
                    ->where('user_id', $user->id)
                    ->where('is_balance', 1)
                    ->orderBy('created_at', 'desc');
        $data = $query->offset($offset)->limit($count)->get(['shop_id','link_id','cover','type','title','created_at','price']);

        foreach ($data as $key => $value) {
            $value->price = $value->price/100;
        }

        return $this->success($data);
    }

    /**
     * 更新用户头像和昵称
     */
    public function updateUserInfo(Request $request){
        $this->validateWith([
            'avatar'   => 'required|string',
            'nickname' => 'required|string',
        ]);
        $avatar   = $request->input('avatar');
        $nickname = $request->input('nickname');

        $user = $this->getUser();

        $tmpName = tempnam(sys_get_temp_dir(), "avatar-");
        copy($avatar, $tmpName);

        $userData = [
            'nickname'   => $nickname,
            'avatar'     => $avatar,
            'avatar_key' => 'avatar/' . $user->id . ".png",
        ];
        $user->update($userData);
        return $this->success();
    }
}
